package cz.vutbr.feec.utko.ef.examples.regression;

import cz.vutbr.feec.utko.ef.evolution.Chromozome;
import cz.vutbr.feec.utko.ef.evolution.IFitnessEvaluator;
import cz.vutbr.feec.utko.ef.gp.tree.TreeChromozome;
import cz.vutbr.feec.utko.ef.individuals.ActionTree;

/**
 * The Class FitnessEvaluatorExample.
 */
public class FitnessEvaluatorExampleRegression implements IFitnessEvaluator {
	
	/** The counter. */
	private int counter = 0;
	
	private double[][] trainingSet;

	/* (non-Javadoc)
	 * @see cz.vutbr.feec.utko.ef.evolution.IFitnessEvaluator#computeFitnessValue(cz.vutbr.feec.utko.ef.individuals.TreeChromozome)
	 */
	@Override
	public double computeFitnessValue(Chromozome ch) {
		return computeFitnessValue((TreeChromozome)ch);
	}
	
	/**
	 * Compute fitness value.
	 * 
	 * @param ch the ch
	 * 
	 * @return the double
	 */
	public double computeFitnessValue(TreeChromozome ch) {
		counter++;
		
		Double suma = 0.0;
		
		if (this.trainingSet == null) {
			throw new RuntimeException("Training set was not specified...");
		}
		
		for (int i = 0; i < this.trainingSet.length; i++) {
			
			ReadNumber r = (ReadNumber) ch.getProgramInputParameter(0);
			r.setValue(this.trainingSet[i][0]);
			
			ReadNumber r2 = (ReadNumber) ch.getProgramInputParameter(1);
			r2.setValue(this.trainingSet[i][1]);
			
			ReadNumber r3 = (ReadNumber) ch.getProgramInputParameter(2);
			r3.setValue(this.trainingSet[i][2]);
			
			ReadNumber r4 = (ReadNumber) ch.getProgramInputParameter(3);
			r4.setValue(this.trainingSet[i][3]);
			
			Double hodnotaChromozomu = (Double)ch.getResult();
			
			Double hodnotaVypoctena = (Double)this.trainingSet[i][4];
			
			Double rozdil = hodnotaChromozomu - hodnotaVypoctena;
			
			Double absHod = Math.abs(rozdil);
			
			suma += absHod;
			
		}
		
		return 1/suma;
	}

	/* (non-Javadoc)
	 * @see cz.vutbr.feec.utko.ef.evolution.IFitnessEvaluator#getNumOfEvaluations()
	 */
	@Override
	public int getNumOfEvaluations() {
		return counter;
	}

	/**
	 * Adds the value vector.
	 * 
	 * @param value the value
	 */
	public void addValueVector(double[][] value) {
		this.trainingSet = value;
	}

	/**
	 * Register parameters.
	 * 
	 * @param r1 the r1
	 * @param r2 the r2
	 * @param i1 the i1
	 * @param i2 the i2
	 */
	public void registerParameters(ActionTree r1, ActionTree r2, ActionTree i1, ActionTree i2) {
		
	}
}
